From 9caeaedfd9c1a834fcaa9eff91bce57f87112f62 Mon Sep 17 00:00:00 2001 From: parkrrrr Date: Wed, 6 Apr 2005 04:57:23 +0000 Subject: [PATCH] Rough but working .an1 support --- gpsbabel/Makefile | 4 +- gpsbabel/README | 16 + gpsbabel/an1.c | 762 ++++++++++++++++++++++++++++++++++++++++++++++ gpsbabel/defs.h | 11 + gpsbabel/route.c | 4 + gpsbabel/vecs.c | 7 + gpsbabel/waypt.c | 8 + 7 files changed, 810 insertions(+), 2 deletions(-) create mode 100644 gpsbabel/an1.c diff --git a/gpsbabel/Makefile b/gpsbabel/Makefile index 1bbd6f590..50fdc9e60 100644 --- a/gpsbabel/Makefile +++ b/gpsbabel/Makefile @@ -27,7 +27,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o garmin_tables.o \ gpilots.o saroute.o navicache.o psitrex.o geoniche.o delgpl.o \ ozi.o nmea.o text.o html.o palmdoc.o netstumbler.o hsa_ndv.o \ igc.o brauniger_iq.o shape.o hiketech.o glogbook.o coastexp.o \ - vcf.o overlay.o kml.o google.o lowranceusr.o + vcf.o overlay.o kml.o google.o lowranceusr.o an1.o FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o reverse_route.o sort.o stackfilter.o @@ -124,6 +124,7 @@ mac-release: # Machine generated from here down. +an1.o: an1.c defs.h queue.h gbtypes.h arcdist.o: arcdist.c defs.h queue.h gbtypes.h grtcirc.h brauniger_iq.o: brauniger_iq.c defs.h queue.h gbtypes.h jeeps/gpsserial.h \ jeeps/gps.h jeeps/gpsport.h jeeps/gpssend.h jeeps/gpsread.h \ @@ -319,4 +320,3 @@ shapelib/dbfopen.o: shapelib/dbfopen.c shapelib/shapefil.h shapelib/shpopen.o: shapelib/shpopen.c shapelib/shapefil.h internal_styles.c: mkstyle.sh style/README.style style/arc.style style/csv.style style/custom.style style/dna.style style/fugawi.style style/gpsdrive.style style/gpsman.style style/mapconverter.style style/mxf.style style/nima.style style/s_and_t.style style/saplus.style style/tabsep.style style/xmap.style style/xmapwpt.style ./mkstyle.sh > internal_styles.c || (rm -f internal_styles.c ; exit 1) - ./mkstyle.sh > internal_styles.c || (rm -f internal_styles.c ; exit 1) diff --git a/gpsbabel/README b/gpsbabel/README index d7b0d8538..2af698072 100644 --- a/gpsbabel/README +++ b/gpsbabel/README @@ -773,6 +773,22 @@ THE FORMATS gpsbabel -i google -f google_map.js -o gpx -F google_map.gpx + AN1 + + This format supports the DeLorme ".an1" drawing file format. It + can currently be used to either read or write drawing files. If + you use this format to create drawing files with routes or waypoints + from another source, it will currently create "Red Flag" symbols + for waypoints, and thick red lines for routes or tracks. It is + possible to merge two drawing layers by doing something like this: + + gpsbabel -i an1 -f one.an1 -f two.an1 -o an1 -F merged.an1 + + Currently, GPSBabel only writes drawing layers. If your input + file is a road, track, trail, or waypoint layer, you should not + attempt to write to an .an1 file as the results may be + unpredictable. + DATA FILTERS GPSBabel supports data filtering. Data filters are invoked from diff --git a/gpsbabel/an1.c b/gpsbabel/an1.c new file mode 100644 index 000000000..739cfb573 --- /dev/null +++ b/gpsbabel/an1.c @@ -0,0 +1,762 @@ +/* + Read DeLorme drawing files (.an1) + + Copyright (C) 2005 Ron Parker and Robert Lipe. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include +#include +#include + +#define MYNAME "an1" +#include "defs.h" + +FILE *infile; +FILE *outfile; + +static char *output_type = NULL; +long output_type_num = 0; + +static long serial=10000; +static long rtserial=1; + +static +arglist_t an1_args[] = { + {"type", &output_type, "Type of .an1 file (0=drawing)", + "0", ARGTYPE_HIDDEN | ARGTYPE_INT }, + {0, 0, 0, 0 } +}; + +static unsigned short +ReadShort(FILE * f) +{ + gbuint16 result = 0; + + fread(&result, sizeof (result), 1, f); + return le_read16(&result); +} + +static void +WriteShort(FILE * f, unsigned short s) +{ + gbuint16 tmp = 0; + le_write16( &tmp, s ); + fwrite( &tmp, sizeof(tmp), 1, f ); +} + +static unsigned long +ReadLong(FILE * f) +{ + gbuint32 result = 0; + + fread(&result, sizeof (result), 1, f); + return le_read32(&result); +} + +static void +WriteLong(FILE * f, unsigned long l) +{ + gbuint32 tmp = 0; + le_write32( &tmp, l ); + + fwrite( &tmp, sizeof(tmp), 1, f ); +} + +static double +ReadDouble( FILE * f ) +{ + double tmp = 0; + double result = 0; + fread(&tmp, sizeof(tmp),1,f); + le_read64(&result, &tmp ); + return result; +} + +static void +WriteDouble(FILE * f, double d) +{ + double tmp = 0; + le_read64( &tmp, (void *)&d ); + fwrite( &tmp, sizeof(tmp), 1, f ); +} + +static char * +ReadString( FILE * f, short len ) +{ + char *result = NULL; + result = (char *)xcalloc( 1, len + 1 ); + if ( len ) { + fread( result, 1, len, f ); + } + return result; +} + +static unsigned char +ReadChar( FILE *f ) +{ + unsigned char result = 0; + fread( &result, 1, 1, f ); + return result; +} + +static void +WriteChar( FILE *f, unsigned char c ) +{ + fwrite( &c, 1, 1, f ); +} + +static void +WriteString( FILE *f, char *s ) +{ + fwrite( s, 1, strlen(s), f ); +} + +static void +Skip(FILE * f, + unsigned long distance) +{ + fseek(f, distance, SEEK_CUR); +} + +static double +DecodeOrd( long ord ) +{ + return (double)(0x80000000-ord)/(0x800000); +} + +static long +EncodeOrd( double ord ) +{ + unsigned long tmp = ord * 0x800000; + return 0x80000000UL-tmp; +} + +typedef struct { + short hotspotxhi; + long hotspoty; + long unk1; + unsigned long guid[4]; + char *name; +} an1_symbol_record; + +typedef struct { + an1_base base; + short magic; + long unk1; + long lon; + long lat; + short type; + long height; + long width; + short unk2; + short unk3; + short serial; + short unk4; + unsigned char create_zoom; + unsigned char visible_zoom; + short unk5; + double radius; + char *name; + char *fontname; + long guid[4]; + long fontcolor; + long fontstyle; + long fontsize; + long outlineweight; + long outlinecolor; + long outlineflags; + long fillcolor; + long unk6; + long fillflags; +} an1_waypoint_record; + +typedef struct { + an1_base base; + short magic; + long unk0; + long lon; + long lat; + short unk1; +} an1_vertex_record; + +typedef struct { + an1_base base; + short magic; + short unk1; + short serial; + long unk2; + short unk3; + short type; + long unk4; + char *name; + long lineweight; + long linestyle; + long linecolor; + long unk5; + long polyfillcolor; + long unk6; + long unk7; + short unk8; + long pointcount; +} an1_line_record; + +static an1_waypoint_record *Alloc_AN1_Waypoint( ); + +void Destroy_AN1_Waypoint( void *vwpt ) { + an1_waypoint_record *wpt = (an1_waypoint_record *)vwpt; + xfree( wpt->name ); + xfree( wpt->fontname ); +} + +void Copy_AN1_Waypoint( void **vdwpt, void *vwpt ) { + an1_waypoint_record *wpt = (an1_waypoint_record *)vwpt; + an1_waypoint_record *dwpt = Alloc_AN1_Waypoint(); + memcpy( dwpt, wpt, sizeof( an1_waypoint_record )); + dwpt->name = xstrdup( wpt->name ); + dwpt->fontname = xstrdup( wpt->fontname ); + *vdwpt = (void *)dwpt; +} + +static an1_waypoint_record *Alloc_AN1_Waypoint( ) { + an1_waypoint_record *result = NULL; + result = (an1_waypoint_record *)xcalloc( sizeof(*result), 1 ); + result->base.copy = Copy_AN1_Waypoint; + result->base.destroy = Destroy_AN1_Waypoint; +} + +static an1_vertex_record *Alloc_AN1_Vertex(); + +void Destroy_AN1_Vertex( void *vvertex ) { + /* do nothing */ +} + +void Copy_AN1_Vertex( void **vdvert, void *vvert ) { + an1_vertex_record *vert = (an1_vertex_record *)vvert; + an1_vertex_record *dvert = Alloc_AN1_Vertex(); + memcpy( dvert, vert, sizeof( an1_vertex_record )); + *vdvert = (void *)dvert; +} + +static an1_vertex_record *Alloc_AN1_Vertex() { + an1_vertex_record *result = NULL; + result = (an1_vertex_record *)xcalloc( sizeof( *result), 1 ); + result->base.copy = Copy_AN1_Vertex; + result->base.destroy = Destroy_AN1_Vertex; +} + + +static an1_line_record *Alloc_AN1_Line(); + +void Destroy_AN1_Line( void *vline ) { + an1_line_record *line = (an1_line_record *)vline; + xfree( line->name ); +} + +void Copy_AN1_Line( void **vdline, void *vline ) { + an1_line_record *line = (an1_line_record *)vline; + an1_line_record *dline = Alloc_AN1_Line(); + memcpy( dline, line, sizeof( an1_line_record )); + dline->name = xstrdup( line->name ); + *vdline = (void *)dline; +} + +static an1_line_record *Alloc_AN1_Line( ) { + an1_line_record *result = NULL; + result = (an1_line_record *)xcalloc( sizeof(*result), 1 ); + result->base.copy = Copy_AN1_Line; + result->base.destroy = Destroy_AN1_Line; +} + + +static void Destroy_AN1_Symbol( an1_symbol_record *symbol ) { + xfree( symbol->name ); +} + +static void Read_AN1_Waypoint( FILE *f, an1_waypoint_record *wpt ) { + short len; + + wpt->magic = ReadShort( f ); + wpt->unk1 = ReadLong( f ); + wpt->lon = ReadLong( f ); + wpt->lat = ReadLong( f ); + wpt->type = ReadShort( f ); + wpt->height = ReadLong( f ); + wpt->width = ReadLong( f ); + wpt->unk2 = ReadShort( f ); + wpt->unk3 = ReadShort( f ); + wpt->serial = ReadShort( f ); + wpt->unk4 = ReadShort( f ); + wpt->create_zoom = ReadChar( f ); + wpt->visible_zoom = ReadChar( f ); + wpt->unk5 = ReadShort( f ); + wpt->radius = ReadDouble( f ); + len = ReadShort( f ); + wpt->name = ReadString( f, len ); + len = ReadShort( f ); + wpt->fontname = ReadString( f, len ); + for ( len = 0; len < 4; len++ ) + wpt->guid[len] = ReadLong( f ); + wpt->fontcolor = ReadLong( f ); + wpt->fontstyle = ReadLong( f ); + wpt->fontsize = ReadLong( f ); + wpt->outlineweight = ReadLong( f ); + wpt->outlinecolor = ReadLong( f ); + wpt->outlineflags = ReadLong( f ); + wpt->fillcolor = ReadLong( f ); + wpt->unk6 = ReadLong( f ); + wpt->fillflags = ReadLong( f ); +} + +static void Write_AN1_Waypoint( FILE *f, an1_waypoint_record *wpt ) { + short len; + + WriteShort( f, wpt->magic ); + WriteLong( f, wpt->unk1 ); + WriteLong( f, wpt->lon ); + WriteLong( f, wpt->lat ); + WriteShort( f, wpt->type ); + WriteLong( f, wpt->height ); + WriteLong( f, wpt->width ); + WriteShort( f, wpt->unk2 ); + WriteShort( f, wpt->unk3 ); + WriteShort( f, wpt->serial ); + WriteShort( f, wpt->unk4 ); + WriteChar( f, wpt->create_zoom ); + WriteChar( f, wpt->visible_zoom ); + WriteShort( f, wpt->unk5 ); + WriteDouble( f, wpt->radius ); + len = strlen( wpt->name ); + WriteShort( f, len ); + WriteString( f, wpt->name ); + len = strlen( wpt->fontname ); + WriteShort( f, len ); + WriteString( f, wpt->fontname ); + for ( len = 0; len < 4; len++ ) + WriteLong( f, wpt->guid[len] ); + WriteLong( f, wpt->fontcolor ); + WriteLong( f, wpt->fontstyle ); + WriteLong( f, wpt->fontsize ); + WriteLong( f, wpt->outlineweight ); + WriteLong( f, wpt->outlinecolor ); + WriteLong( f, wpt->outlineflags ); + WriteLong( f, wpt->fillcolor ); + WriteLong( f, wpt->unk6 ); + WriteLong( f, wpt->fillflags ); +} + +static void Read_AN1_Vertex( FILE *f, an1_vertex_record *vertex ) { + + vertex->magic = ReadShort( f ); + vertex->unk0 = ReadLong( f ); + vertex->lon = ReadLong( f ); + vertex->lat = ReadLong( f ); + vertex->unk1 = ReadShort( f ); +} + +static void Write_AN1_Vertex( FILE *f, an1_vertex_record *vertex ) { + WriteShort( f, vertex->magic ); + WriteLong( f, vertex->unk0 ); + WriteLong( f, vertex->lon ); + WriteLong( f, vertex->lat ); + WriteShort( f, vertex->unk1 ); +} + +static void Read_AN1_Line( FILE *f, an1_line_record *line ) { + + short len; + + line->magic = ReadShort( f ); + line->unk1 = ReadShort( f ); + line->serial = ReadShort( f ); + line->unk2 = ReadLong( f ); + line->unk3 = ReadShort( f ); + line->type = ReadShort( f ); + line->unk4 = ReadLong( f ); + len = ReadShort( f ); + line->name = ReadString( f, len ); + line->lineweight = ReadShort( f ); + line->linestyle = ReadLong( f ); + line->linecolor = ReadLong( f ); + line->unk5 = ReadLong( f ); + line->polyfillcolor = ReadLong( f ); + line->unk6 = ReadLong( f ); + line->unk7 = ReadLong( f ); + line->unk8 = ReadShort( f ); + line->pointcount = ReadLong( f ); +} + +static void Write_AN1_Line( FILE *f, an1_line_record *line ) { + short len; + + WriteShort( f, line->magic ); + WriteShort( f, line->unk1 ); + WriteShort( f, line->serial ); + WriteLong( f, line->unk2 ); + WriteShort( f, line->unk3 ); + WriteShort( f, line->type ); + WriteLong( f, line->unk4 ); + len = strlen( line->name ); + WriteShort( f, len ); + WriteString( f, line->name ); + WriteShort( f, line->lineweight ); + WriteLong( f, line->linestyle ); + WriteLong( f, line->linecolor ); + WriteLong( f, line->unk5 ); + WriteLong( f, line->polyfillcolor ); + WriteLong( f, line->unk6 ); + WriteLong( f, line->unk7 ); + WriteShort( f, line->unk8 ); + WriteLong( f, line->pointcount ); +} + +static void Skip_AN1_IL( FILE *f ) { + Skip( f, 26 ); +} + +static void Skip_AN1_BM( FILE *f ) { + unsigned long bmsize; + unsigned long palettesize; + unsigned long bmisize; + unsigned long bitoffset; + + Skip( f, 8 ); /* BITMAPFILEHEADER fields 1-3 */ + bitoffset = ReadLong( f ); + + bmisize = ReadLong( f ); + Skip( f, 16 ); /* BITMAPINFOHEADER fields 2-6 */ + bmsize = ReadLong( f ); + Skip( f, 16 ); /* BITMAPINFOHEADER fields 8-11 */ + + palettesize = bitoffset - bmisize - 14; + Skip( f, bmsize + palettesize ); +} + +static void Read_AN1_Symbol( FILE *f, an1_symbol_record *symbol ) { + short len; + + /* This is just the high word of a long; we ate the low + * word in the caller. Fortunately, we don't care. */ + symbol->hotspotxhi = ReadShort( f ); + symbol->hotspoty = ReadLong( f ); + symbol->unk1 = ReadLong( f ); + for ( len = 0; len < 4; len++ ) { + symbol->guid[len] = ReadLong( f ); + } + len = ReadChar( f ); + symbol->name = ReadString( f, len ); +} + +static void Read_AN1_Header( FILE *f ) { + unsigned short magic; + unsigned short type; + + magic = ReadShort( f ); + type = ReadShort( f ); +} + +static void Write_AN1_Header( FILE *f ) { + WriteShort( f, 11557 ); + WriteShort( f, atoi( output_type ) ); +} + +static void Read_AN1_Bitmaps( FILE *f ) { + long count; + unsigned short magic; + an1_symbol_record symbol; + + count = ReadLong( f ); + + while ( count ) { + magic = ReadShort( f ); + switch (magic) { + case 0x4d42: + Skip_AN1_BM( f ); + break; + case 0x4c49: + Skip_AN1_IL( f ); + break; + default: + Read_AN1_Symbol( f, &symbol ); + Destroy_AN1_Symbol( &symbol ); + count--; + break; + } + } + + /* Read the symbol table */ +} + +static void Write_AN1_Bitmaps( FILE *f ) { + /* On write, we don't output any bitmaps, so writing them + * is just a matter of writing a count of zero */ + WriteLong( f, 0 ); +} + +static void Read_AN1_Waypoints( FILE *f ) { + unsigned long count = 0; + unsigned long i = 0; + an1_waypoint_record *rec = NULL; + waypoint *wpt_tmp; + ReadShort( f ); + count = ReadLong( f ); + for (i = 0; i < count; i++ ) { + rec = Alloc_AN1_Waypoint(); + Read_AN1_Waypoint( f, rec ); + wpt_tmp = waypt_new(); + + wpt_tmp->longitude = -DecodeOrd( rec->lon ); + wpt_tmp->latitude = DecodeOrd( rec->lat ); + wpt_tmp->description = xstrdup( rec->name ); + wpt_tmp->an1_extras = (an1_base *)(void *)rec; + rec = NULL; + waypt_add( wpt_tmp ); + } +} + +static void +Write_One_AN1_Waypoint( const waypoint *wpt ) +{ + an1_waypoint_record *rec; + int local; + + if ( wpt->an1_extras ) { + rec = (an1_waypoint_record *)(void *)(wpt->an1_extras); + xfree( rec->name ); + local = 0; + } + else { + rec = Alloc_AN1_Waypoint(); + local = 1; + rec->magic = 1; + rec->type = 1; + rec->unk2 = 3; + rec->unk3 = 18561; + rec->fontname = xstrdup( "Arial" ); + rec->guid[0] = 1648238304; + rec->guid[1] = 299085607; + rec->guid[2] = 1342187964; + rec->guid[3] = 854917636; + rec->fontsize = 10; + } + rec->name = xstrdup( wpt->description ); + rec->lat = EncodeOrd( wpt->latitude ); + rec->lon = EncodeOrd( -wpt->longitude ); + rec->serial = serial++; + + Write_AN1_Waypoint( outfile, rec ); + if ( local ) { + Destroy_AN1_Waypoint( rec ); + xfree( rec ); + } +} + +static void Write_AN1_Waypoints( FILE *f ) { + WriteShort( f, 2 ); + WriteLong( f, waypt_count() ); + waypt_disp_all( Write_One_AN1_Waypoint ); +} + +static void Read_AN1_Lines( FILE *f ) { + unsigned long count = 0; + unsigned long i = 0; + unsigned long j = 0; + an1_line_record *rec = NULL; + an1_vertex_record *vert = NULL; + route_head *rte_head; + waypoint *wpt_tmp; + + ReadShort( f ); + count = ReadLong( f ); + for (i = 0; i < count; i++ ) { + rec = Alloc_AN1_Line(); + Read_AN1_Line( f, rec ); + /* create route rec */ + rte_head = route_head_alloc(); + rte_head->an1_extras = (an1_base *)(void *)rec; + route_add_head(rte_head); + for (j = 0; j < rec->pointcount; j++ ) { + vert = Alloc_AN1_Vertex(); + Read_AN1_Vertex( f, vert ); + + /* create route point */ + wpt_tmp = waypt_new(); + wpt_tmp->latitude = DecodeOrd( vert->lat ); + wpt_tmp->longitude = -DecodeOrd( vert->lon ); + wpt_tmp->shortname = (char *) xmalloc(7); + sprintf( wpt_tmp->shortname, "\\%5.5x", rtserial++ ); + wpt_tmp->an1_extras = (an1_base *)(void *)vert; + route_add_wpt(rte_head, wpt_tmp); + } + } +} + +static void +Write_One_AN1_Line( const route_head *rte ) +{ + an1_line_record *rec; + int local; + + if ( rte->an1_extras ) { + rec = (an1_line_record *)(void *)(rte->an1_extras); + local = 0; + } + else { + rec = Alloc_AN1_Line(); + local = 1; + switch (output_type_num) { + /* drawing road trail waypoint track */ + case 1: /* road */ + rec->magic = 4112; + rec->unk1 = 4359; + rec->unk2 = 655360; + rec->type = 14; + rec->unk8 = 2; + break; + + case 2: /* trail */ + rec->magic = 7248; + rec->unk1 = 4359; + rec->unk2 = 917504; + rec->type = 15; + rec->unk8 = 2; + break; + + case 4: /* track */ + rec->magic = 21; + rec->unk1 = 18560; + rec->unk2 = 917504; + rec->type = 16; + rec->unk4 = 2; + rec->unk8 = 2; + break; + + case 0: /* drawing */ + case 3: /* waypoint - shouldn't have lines */ + default: + rec->magic = 21; + rec->unk1 = 18560; + rec->unk2 = 1048576; + rec->type = 2; + rec->unk4 = 2; + rec->lineweight = 6; + rec->linecolor = 255; /* red */ + rec->unk5 = 3; + rec->unk8 = 2; + break; + } + rec->name = xstrdup( "" ); + + } + rec->serial = serial++; + rec->pointcount = rte->rte_waypt_ct; + Write_AN1_Line( outfile, rec ); + if ( local ) { + Destroy_AN1_Line( rec ); + xfree( rec ); + } +} + +static void +Write_One_AN1_Vertex( const waypoint *wpt ) +{ + an1_vertex_record *rec; + int local; + + if ( wpt->an1_extras ) { + rec = (an1_vertex_record *)(void *)(wpt->an1_extras); + local = 0; + } + else { + rec = Alloc_AN1_Vertex(); + local = 1; + rec->magic = 1; + } + rec->lat = EncodeOrd( wpt->latitude ); + rec->lon = EncodeOrd( -wpt->longitude ); + + Write_AN1_Vertex( outfile, rec ); + if ( local ) { + Destroy_AN1_Vertex( rec ); + xfree( rec ); + } +} + +static void Write_AN1_Lines( FILE *f ) { + WriteShort( f, 2 ); + WriteLong( f, route_count()+track_count() ); + + route_disp_all( Write_One_AN1_Line, NULL, Write_One_AN1_Vertex ); + track_disp_all( Write_One_AN1_Line, NULL, Write_One_AN1_Vertex ); +} + +static void +rd_init(const char *fname) +{ + infile = xfopen(fname, "rb", MYNAME); + output_type_num = atoi( output_type ); +} + +static void +rd_deinit(void) +{ + fclose(infile); +} + +static void +my_read(void) +{ + Read_AN1_Header( infile ); + Read_AN1_Bitmaps( infile ); + Read_AN1_Waypoints( infile ); + Read_AN1_Lines( infile ); +} + +static void +wr_init(const char *fname) +{ + outfile = xfopen( fname, "wb", MYNAME ); + output_type_num = atoi( output_type ); +} + +static void +wr_deinit( void ) +{ + fclose(outfile); +} + +static void +my_write( void ) +{ + Write_AN1_Header( outfile ); + Write_AN1_Bitmaps( outfile ); + Write_AN1_Waypoints( outfile ); + Write_AN1_Lines( outfile ); +} + +ff_vecs_t an1_vecs = { + ff_type_file, + FF_CAP_RW_ALL, + rd_init, + wr_init, + rd_deinit, + wr_deinit, + my_read, + my_write, + NULL, + an1_args +}; diff --git a/gpsbabel/defs.h b/gpsbabel/defs.h index 93eaa0c19..ae933b01f 100644 --- a/gpsbabel/defs.h +++ b/gpsbabel/defs.h @@ -151,6 +151,13 @@ typedef struct xml_tag { struct xml_tag *child; } xml_tag ; +typedef void (*an1_destroy)(void *); +typedef void (*an1_copy)(void **, void *); +typedef struct { + an1_destroy destroy; + an1_copy copy; +} an1_base; + /* * This is a waypoint, as stored in the GPSR. It tries to not * cater to any specific model or protocol. Anything that needs to @@ -214,11 +221,14 @@ typedef struct { * This causes it to be removed last. * This is currently used by the saroute input filter to give named * waypoints (representing turns) a higher priority. + * This is also used by the google input filter because they were + * nice enough to use exactly the same priority scheme. */ int route_priority; geocache_data gc_data; xml_tag *gpx_extras; + an1_base *an1_extras; void *extra_data; /* Extra data added by, say, a filter. */ } waypoint; @@ -229,6 +239,7 @@ typedef struct { char *rte_desc; int rte_num; int rte_waypt_ct; /* # waypoints in waypoint list */ + an1_base *an1_extras; } route_head; /* diff --git a/gpsbabel/route.c b/gpsbabel/route.c index b06ce2bb8..545da8210 100644 --- a/gpsbabel/route.c +++ b/gpsbabel/route.c @@ -128,6 +128,10 @@ route_free(route_head *rte) } rte_waypts -= rte->rte_waypt_ct; waypt_flush(&rte->waypoint_list); + if ( rte->an1_extras ) { + (*(rte->an1_extras->destroy))((void *)rte->an1_extras ); + xfree( rte->an1_extras ); + } xfree(rte); } diff --git a/gpsbabel/vecs.c b/gpsbabel/vecs.c index c67cfd06e..42734e795 100644 --- a/gpsbabel/vecs.c +++ b/gpsbabel/vecs.c @@ -76,6 +76,7 @@ extern ff_vecs_t vcf_vecs; extern ff_vecs_t overlay_vecs; extern ff_vecs_t kml_vecs; extern ff_vecs_t google_vecs; +extern ff_vecs_t an1_vecs; static vecs_t vec_list[] = { @@ -356,6 +357,12 @@ vecs_t vec_list[] = { "Google Maps XML", "xml" }, + { + &an1_vecs, + "an1", + "DeLorme .an1 (drawing) file", + "an1" + }, { NULL, NULL, diff --git a/gpsbabel/waypt.c b/gpsbabel/waypt.c index ae15046f4..14305d98c 100644 --- a/gpsbabel/waypt.c +++ b/gpsbabel/waypt.c @@ -66,6 +66,10 @@ waypt_dupe(const waypoint *wpt) */ tmp->Q.next = tmp->Q.prev = NULL; tmp->gpx_extras = NULL; + if ( wpt->an1_extras ) { + wpt->an1_extras->copy((void **)(&tmp->an1_extras), + (void *)wpt->an1_extras ); + } return tmp; } @@ -270,6 +274,10 @@ waypt_free( waypoint *wpt ) if (wpt->gc_data.desc_long.utfstring) { xfree(wpt->gc_data.desc_long.utfstring); } + if ( wpt->an1_extras ) { + (*(wpt->an1_extras->destroy))((void *)wpt->an1_extras ); + xfree( wpt->an1_extras ); + } xfree(wpt); } -- 2.30.2